const {handleWhere, getCloud} = require('../../sync/')
const {getResult, getError} = require('../../handle')

/**
 * 一般都要去除两个字段 - HISTORY和remove
 * 去除与否或者去除其它字段，在config.defuseKeys中设置
 */
const handleDefuseKey = (data = [], defuseKeys = ['HISTORY', 'remove']) => {
	if (typeof(defuseKeys) === 'string') {
		defuseKeys = defuseKeys.split(',')
	}
	if (Array.isArray(defuseKeys) && defuseKeys.length > 0) {
		data.map(item => {
			defuseKeys.map(key => {
				delete item[key]
			})
		})
	}
}

/**
 * 联表查询 - 即使没有联表数据，也会处理掉不需要的字段
 * foreign是对象数组。每个对象元素表示一层数据的一张表
 * 返回数据是在原来联表字段新增一个${key}_copy的字段。原来字段是是数组则是对象数组，原来字段非数组则是对象
 * 
 * 	space：对应表的云服务空间。不传，默认为当前云服务空间
 * 	name：对应表的名称。系统字段foreignKey的前部分。至少每一层不能重复，如果有多个，在foreignKey中添加字段映射即可
 *  foreignKey：对象。key表示当前字段名，value表示对应表的字段名。
 * 	field：返回字段要求。一定要包含foreignKey中的字段，否则联表数据为空。默认也会追加foreignKey中的字段
 * 	children：多重联表的要求，结构同foreign
 * 示例：
 * [{
	space: 'capfer', 
	name: 'a-user'
	foreignKey: {
		phone: 'phone',
		user_id: '_id',
		creator: '_id',
		alert_user: '_id'
	}
	field: 'name,nickname,phone,gender'
 * }]
 */
const handleDefuseForeign = (data, foreign, config, isApp = false) =>  {
	const {defuseKeys} = config
	// 没有reject
	return new Promise((resolve) => {
		if (data.length > 0) {
			// 处理不需要的数据
			handleDefuseKey(data, defuseKeys)
			if (foreign) {
				if (!Array.isArray(foreign)) {
					foreign = [foreign]
				}
				/**
				 * 每一层的数据处理
				 * 只有等到每一层的数据处理完毕之后，才可能对下一层数据再联表
				 */
				const cycle = (index = 0) => {
					if (index < foreign.length) {
						// 获取当前层所有需要联表的数据库信息
						const {name, space, foreignKey, field, children} = foreign[index]
						const fieldArr =  field ? field.split(',') : []
						Object.keys(foreignKey).forEach(key => {
							if (field.indexOf(foreignKey[key]) === -1) {
								fieldArr.push(foreignKey[key])
							}
						})
						const params = {field: fieldArr.join(',')}
						data.map(record => {
							// 处理联表字段
							Object.keys(foreignKey).forEach(key => {
								if (Array.isArray(record[key])) {
									// 当联表字段是数组时
									if (params[foreignKey[key]]) {
										record[key].map(res => {
											if (params[foreignKey[key]].filter.indexOf(res) === -1) {
												params[foreignKey[key]].filter.push(res)
											}
										})
									} else {
										params[foreignKey[key]] = {
											filterType: 'select', filter: record[key]
										}
									}
								} else {
									if (params[foreignKey[key]]) {
										if (params[foreignKey[key]].filter.indexOf(record[key]) === -1) {
											params[foreignKey[key]].filter.push(record[key])
										}
									} else {
										params[foreignKey[key]] = {
											filterType: 'select', filter: [record[key]]
										}
									}
								}
							})
						})
						const {text, cloud} = getCloud({space, name, type: 'get'}, true)
						const db = handleWhere({cloud, name, space}, params, config, isApp, true)
						if (db) {
							db.get().then(res => {
								if (res.result) {
									res = res.result
								}
								// 当前数据查询来之后，立即给数据源赋值
								data.map(record => {
									Object.keys(foreignKey).forEach(key => {
										if (Array.isArray(record[key])) {
											const arr = []
											for (let i = 0; i < res.data.length; i++) {
												if (record[key].indexOf(res.data[i][foreignKey[key]]) > -1) {
													arr.push(res.data[i])
												}
											}
											record[`${key}_copy`] = arr
										} else {
											for (let i = 0; i < res.data.length; i++) {
												if (record[key] === res.data[i][foreignKey[key]]) {
													record[`${key}_copy`] = res.data[i]
													break
												}
											}
										}
									})
								})
								// 赋值完成后，继续下一层联表，没有children会自动返回。同主函数调用
								handleDefuseForeign(res.data, children, config, isApp).then(res => {
									// 内部处理完了
									cycle(index + 1)
								})
							}).catch(err => {
								// 请求错误当做是内部处理完了
								cycle(index + 1)
							})
						} else {
							// 不存，当做是内部处理完了
							cycle(index + 1)
						}
					} else {
						// 处理完了
						resolve()
					}
				}
				cycle(0)
			} else {
				resolve()
			}
		} else {
			resolve()
		}
	})
}

/**
 * 前端查询可以直接获取到count。后端非jql查询，则需要专门获取count
 */
const handleCount = (count, getCount, db) => {
	return new Promise((resolve, reject) => {
		if (count > 0) {
			resolve(count)
		} else if (getCount) {
			db.count().then(res => {
				if (res.result) {
					res = res.result
				}
				resolve(res.total)
			}).catch(err => {
				resolve(0)
			})
		} else {
			resolve(0)
		}
	})
}

/**
 * 查询处理
 * OnlyCount: 只查询数量
 * pagination = 'all', 查询所有。将会遍历查询，直到查询完毕
 */
module.exports = (cloudObj = {}, params, config = {}, isApp = false) => {
	const {cloud, name, space} = cloudObj
	const {OnlyCount} = params || {}
	var isAll = false
	if (params && params.pagination === 'all') {
		isAll = true
		params.pagination = {
			pageIndex: 0,
			pageSize: 1000
		}
	}
	const result = {
		data: [],
		message: ''
	}
	const single = () => { // 单次查询
		return new Promise((resolve, reject) => {
			var getTree, getTreePath, getCount, foreign, pagination
			const db = handleWhere(cloudObj, params ? JSON.parse(JSON.stringify(params)) : undefined, config, isApp, (res) => {
				foreign = res.foreign
				getTree = res.getTree
				getTreePath = res.getTreePath
				// 分页查询，一定要查询数量
				pagination = res.pagination
				getCount = res.getCount || !!pagination
			})
			if (db) {
				var getParams = getTree || getTreePath || getCount ? {} : undefined
				if (getTree) {
					getParams.getTree = getTree
				}
				if (getTreePath) {
					getParams.getTreePath = getTreePath
				}
				if (getCount) {
					getParams.getCount = getCount
				}
				if (OnlyCount) {
					handleCount(undefined, true, db).then(res => {
						resolve(getResult({
							message: `查询数量成功：${res}条`,
							data: res
						}))
					}).catch(reject)
				} else {
					db.get(getParams).then(res => {
						if (res.result) {
							res = JSON.parse(JSON.stringify(res.result))
						}
						var {count = 0, data = []} = res
						Promise.all([
							handleCount(count, getCount, db),
							handleDefuseForeign(res.data, foreign, config, isApp)
						]).then(arr => {
							count = arr[0]
							result.data = result.data.concat(res.data)
							var message = `查询到${result.data.length}条数据${getCount ? `。共${count}条` : ''}`
							// 页码处理
							if (pagination) {
								const {pageSize, pageIndex} = pagination
								var pageNumber = parseInt(count / pageSize)
								if (pageNumber * pageSize < count) {
									pageNumber += 1
								}
								pagination.pageNumber = pageNumber
								pagination.total = count
								result.pagination = pagination
								if (isAll) {
									if (result.data.length < count) {
										params.pagination.pageIndex += 1
										single().then(resolve).catch(reject)
									} else {
										result.message = message + '。'
										resolve(getResult(result))
									}
									return
								} else {
									message += `，分${pageNumber}页，每页${pageSize}条，当前第${pageIndex + 1}页。`
								}
							} else {
								message += '。'
							}
							result.message = message
							resolve(getResult(result))
						})
					}).catch(reject)
				}
			} else {
				reject(getError('没有云服务对象'))
			}
		})
	}
	return single()
}